package com.hksj.Intelligentmanagement.service;


import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hksj.Intelligentmanagement.common.Result;
import com.hksj.Intelligentmanagement.dto.DicInfoDTO;
import com.hksj.Intelligentmanagement.entity.DicInfoEntity;
import com.hksj.Intelligentmanagement.entity.DicTypeEntity;
import com.hksj.Intelligentmanagement.mapper.DicInfoMapper;
import com.hksj.Intelligentmanagement.mapper.DicTypeMapper;
import com.hksj.Intelligentmanagement.vo.DicInfoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class DicInfoService {
    @Autowired
    private DicInfoMapper dicInfoMapper;

    @Autowired
    private DicTypeMapper dicTypeMapper;


    //创建字典类型
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Result addDicInfo(DicInfoDTO dicInfoDTO) {
        //创建一个字典类型实例
        DicInfoEntity dicInfoEntity = new DicInfoEntity();
        //将前端传回的数据复制到dictionaryTypeEntity中
        BeanUtils.copyProperties(dicInfoDTO, dicInfoEntity);
        //在数据库中插入该记录
        int insert = dicInfoMapper.insert(dicInfoEntity);
        if (insert <= 0) {
            return Result.error("新增失败");
        }
        return Result.ok("新增字典类型成功");
    }

    //删除字典类型 那么字典类型下挂的字典明细也全部删除
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Result deleteDicInfo(String id) {
        //删除字典明细
        int insert = dicInfoMapper.deleteById(id);
        //一定有对应的子项吗
        if (insert <= 0 ) {
            return Result.error("删除失败");
        }
        return Result.ok("删除成功");
    }

    //更新字典类型
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Result updateDicInfo(DicInfoDTO dicInfoDTO) {
        DicInfoEntity dicInfoEntity = new DicInfoEntity();
        BeanUtils.copyProperties(dicInfoDTO, dicInfoEntity);
        int i = dicInfoMapper.updateById(dicInfoEntity);
        if (i <= 0) {
            return Result.error("更新失败");
        }
        return Result.ok("更新成功");
    }

    //根据id查询字典明细
    public Result queryDicInfoById(String id) {
        //调用selectById查询专业信息
        DicInfoEntity entity = dicInfoMapper.selectById(id);
        //返回查询结果
        return Result.data(entity);
    }

    //根据专业id查询所有字典明细 递归查成树https://blog.csdn.net/sinat_40572875/article/details/128129072
    public DicTypeEntity queryDicInfoAllByTypeId(String typeId) {
        //查询专业id对应的专业信息
        DicTypeEntity dicInfoEntity = dicTypeMapper.selectById(typeId);
        //专业id对应字典明细的字典明细
        List<DicInfoVo>dicInfoVos=dicInfoMapper.queryDicInfoListByTypeId(typeId);
        TreeBuild treeBuild = new TreeBuild(dicInfoVos);
        // 原查询结果转换树形结构
        dicInfoVos = treeBuild.buildTree();
        dicInfoEntity.setList(dicInfoVos);
        return dicInfoEntity;
    }

    //递归构建树方法
    public class TreeBuild {

        //接收需要递归的数据
        public List<DicInfoVo> nodeList = new ArrayList<>();

        //存储所有数据
        public TreeBuild(List<DicInfoVo> nodeList) {
            this.nodeList = nodeList;
        }

        //构建根节点 pid为0的节点 可以通过数据库直接查出pid=0的集合
        public List<DicInfoVo> getRootNode() {
            // 保存所有根节点（所有根节点的数据）
            List<DicInfoVo> rootNodeList = new ArrayList<>();
            // treeNode：查询出的每一条数据（节点）
            for (DicInfoVo treeNode : nodeList) {
                // 判断当前节点是否为根节点，此处注意：若parentId类型是String，则要采用equals()方法判断。
                if (StringUtils.isBlank(treeNode.getParentId())) {
                    rootNodeList.add(treeNode);
                }
            }
            return rootNodeList;
        }
        //遍历为pid为0的根节点构建子树
        public List<DicInfoVo> buildTree() {
            // treeNodes：保存一个顶级节点所构建出来的完整树形
            List<DicInfoVo> treeNodes = new ArrayList<DicInfoVo>();
            // getRootNode()：获取所有的根节点
            for (DicInfoVo treeRootNode : getRootNode()) {
                // 将顶级节点进行构建子树
                treeRootNode = buildChildTree(treeRootNode);
                // 完成一个顶级节点所构建的树形，增加进来
                treeNodes.add(treeRootNode);
            }
            return treeNodes;
        }

        //通过递归构建子树 注意nodeList所有数据查询不要放在方法buildChildTree中遍历调用buildChildTree时会反复查询数据库
        public DicInfoVo buildChildTree(DicInfoVo pNode) {
            List<DicInfoVo> childTree = new ArrayList<DicInfoVo>();
            // nodeList：所有节点集合（所有数据）
            for (DicInfoVo treeNode : nodeList) {
                // 判断当前节点的父节点ID是否等于根节点的ID，即当前节点为其下的子节点
                if (treeNode.getParentId().equals(pNode.getId())) {//注意数据类型
                    // 再递归进行判断当前节点的情况，调用自身方法
                    childTree.add(buildChildTree(treeNode));//递归数据层数过多时多次遍历nodeList可用stream流来提高效率
                }
            }
            // for循环结束，即节点下没有任何节点，树形构建结束，设置树结果
            pNode.setList(childTree);
            return pNode;
        }
    }

}
